/*!
 * \file WtDataReaderAD.h
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader高级数据读取器头文件
 * 
 * \details 该文件定义了WtDataReaderAD类，提供高级数据存储系统的数据读取功能，包括：
 *          - LMDB数据库集成：使用Lightning Memory-Mapped Database进行高性能数据存储
 *          - 多周期K线数据读取：支持分钟级(m1/m5)和日线级(d1)数据
 *          - Tick数据读取：支持高频Tick数据的快速检索
 *          - 内存缓存机制：通过循环缓冲区和内存映射文件优化性能
 *          - 实时数据缓存：支持实时K线和Tick数据的缓存更新
 *          
 *          与标准WtDataReader相比，WtDataReaderAD提供：
 *          - 更高的数据读取性能
 *          - 更大的数据容量支持
 *          - 更灵活的缓存策略
 *          - 更好的内存效率
 */

#pragma once
#include <string>
#include <stdint.h>
#include <boost/circular_buffer.hpp>

#include "DataDefineAD.h"

#include "../WTSUtils/WtLMDB.hpp"
#include "../Includes/FasterDefs.h"
#include "../Includes/IDataReader.h"

#include "../Share/StdUtils.hpp"
#include "../Share/BoostMappingFile.hpp"

NS_WTP_BEGIN

typedef std::shared_ptr<BoostMappingFile> BoostMFPtr;	///< Boost内存映射文件智能指针类型定义

/*!
 * \class WtDataReaderAD
 * \brief WonderTrader高级数据读取器类
 * 
 * \details 高级数据读取器，基于LMDB数据库和内存映射技术实现高性能数据读取。
 *          该类提供以下核心功能：
 *          
 *          1. 多周期K线数据读取：
 *             - 1分钟K线(m1)
 *             - 5分钟K线(m5)  
 *             - 日线K线(d1)
 *          
 *          2. Tick数据读取：
 *             - 高频Tick数据
 *             - 按时间范围检索
 *             - 内存缓存优化
 *          
 *          3. 缓存机制：
 *             - 实时数据缓存
 *             - 历史数据缓存
 *             - 循环缓冲区优化
 *          
 *          4. 数据库管理：
 *             - 按交易所分库存储
 *             - LMDB事务管理
 *             - 自动索引维护
 * 
 * \note 该类使用LMDB作为底层存储引擎，适用于大数据量场景
 * \warning 需要确保LMDB数据库文件的正确性和完整性
 * \see IDataReader, WtLMDB, DataDefineAD.h
 */
class WtDataReaderAD : public IDataReader
{
public:
	WtDataReaderAD();
	virtual ~WtDataReaderAD();

public:
	/*!
	 * \brief 初始化数据读取器
	 * \param cfg 配置参数
	 * \param sink 数据读取回调接口
	 * \param loader 历史数据加载器（可选）
	 * 
	 * 初始化LMDB数据库连接，设置缓存参数，建立数据读取环境
	 */
	virtual void init(WTSVariant* cfg, IDataReaderSink* sink, IHisDataLoader* loader = NULL) override;

	/*!
	 * \brief 分钟结束时的数据处理
	 * \param uDate 日期
	 * \param uTime 时间
	 * \param endTDate 结束交易日期（可选）
	 * 
	 * 在每分钟结束时触发，用于更新实时数据缓存和同步LMDB数据
	 */
	virtual void onMinuteEnd(uint32_t uDate, uint32_t uTime, uint32_t endTDate = 0) override;

	/*!
	 * \brief 读取Tick数据切片
	 * \param stdCode 标准合约代码
	 * \param count 数据条数
	 * \param etime 结束时间（0表示最新数据）
	 * \return Tick数据切片指针
	 * 
	 * 从LMDB数据库读取指定数量的Tick数据，支持缓存机制优化性能
	 */
	virtual WTSTickSlice*	readTickSlice(const char* stdCode, uint32_t count, uint64_t etime = 0) override;

	/*!
	 * \brief 读取K线数据切片
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param count 数据条数
	 * \param etime 结束时间（0表示最新数据）
	 * \return K线数据切片指针
	 * 
	 * 从LMDB数据库读取指定数量的K线数据，支持多周期和缓存优化
	 */
	virtual WTSKlineSlice*	readKlineSlice(const char* stdCode, WTSKlinePeriod period, uint32_t count, uint64_t etime = 0) override;

private:
	std::string		_base_dir;			///< 数据存储根目录
	IBaseDataMgr*	_base_data_mgr;		///< 基础数据管理器指针
	IHotMgr*		_hot_mgr;			///< 主力合约管理器指针

	/*!
	 * \struct _RTBarCacheWrapper
	 * \brief 实时K线缓存包装器结构体
	 * 
	 * \details 用于管理实时K线数据的内存缓存，包含：
	 *          - 线程安全的互斥锁
	 *          - 内存映射文件管理
	 *          - 数据索引映射
	 *          - 缓存块指针
	 *          - 大小状态追踪
	 */
	typedef struct _RTBarCacheWrapper
	{
		StdUniqueMutex	_mtx;			///< 线程安全互斥锁
		std::string		_filename;		///< 缓存文件名
		faster_hashmap<std::string, uint32_t> _idx;	///< 数据索引映射表
		BoostMFPtr		_file_ptr;		///< 内存映射文件指针
		RTBarCache*		_cache_block;	///< 实时K线缓存块指针
		uint32_t		_last_size;		///< 上次缓存大小

		_RTBarCacheWrapper() :_cache_block(NULL), _file_ptr(NULL), _last_size(0){}

		/*!
		 * \brief 检查缓存是否为空
		 * \return true表示缓存为空，false表示缓存有数据
		 */
		inline bool empty() const { return _cache_block == NULL; }
	} RTBarCacheWrapper;

	RTBarCacheWrapper _m1_cache;		///< 1分钟K线缓存
	RTBarCacheWrapper _m5_cache;		///< 5分钟K线缓存
	RTBarCacheWrapper _d1_cache;		///< 日线K线缓存

	/*!
	 * \struct _BarsList
	 * \brief K线数据列表结构体
	 * 
	 * \details 用于管理特定合约的K线数据缓存，包含：
	 *          - 交易所和合约信息
	 *          - K线周期类型
	 *          - 缓存状态追踪
	 *          - 循环缓冲区存储
	 */
	typedef struct _BarsList
	{
		std::string		_exchg;				///< 交易所代码
		std::string		_code;				///< 合约代码
		WTSKlinePeriod	_period;			///< K线周期
		bool			_last_from_cache;	///< 上次数据是否来自缓存（用于优化LMDB查询）
		uint64_t		_last_req_time;		///< 上次请求时间戳

		boost::circular_buffer<WTSBarStruct>	_bars;	///< 循环缓冲区存储K线数据

		_BarsList():_last_from_cache(false),_last_req_time(0){}
	} BarsList;

	/*!
	 * \struct _TicksList
	 * \brief Tick数据列表结构体
	 * 
	 * \details 用于管理特定合约的Tick数据缓存，包含：
	 *          - 交易所和合约信息
	 *          - 请求时间追踪
	 *          - 循环缓冲区存储
	 */
	typedef struct _TicksList
	{
		std::string		_exchg;			///< 交易所代码
		std::string		_code;			///< 合约代码
		uint64_t		_last_req_time;	///< 上次请求时间戳

		boost::circular_buffer<WTSTickStruct>	_ticks;	///< 循环缓冲区存储Tick数据

		_TicksList():_last_req_time(0){}
	} TicksList;

	typedef faster_hashmap<std::string, BarsList> BarsCache;	///< K线缓存映射表类型定义
	BarsCache	_bars_cache;	///< K线数据缓存

	typedef faster_hashmap<std::string, TicksList> TicksCache;	///< Tick缓存映射表类型定义
	TicksCache	_ticks_cache;	///< Tick数据缓存

	uint64_t	_last_time;		///< 上次处理时间戳

private:
	/*!
	 * \brief 从存储中缓存历史K线数据
	 * \param key 缓存键值
	 * \param stdCode 标准合约代码
	 * \param period K线周期
	 * \param count 数据条数
	 * \return 缓存操作是否成功
	 * 
	 * 从LMDB数据库读取历史K线数据并加载到内存缓存中
	 */
	bool	cacheBarsFromStorage(const std::string& key, const char* stdCode, WTSKlinePeriod period, uint32_t count);

	/*!
	 * \brief 从LMDB更新缓存数据
	 * \param barsList K线数据列表引用
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \param period K线周期
	 * \param lastBarTime 最后K线时间引用
	 * 
	 * 从LMDB数据库获取最新数据并更新到内存缓存中
	 */
	void	update_cache_from_lmdb(BarsList& barsList, const char* exchg, const char* code, WTSKlinePeriod period, uint32_t& lastBarTime);

	/*!
	 * \brief 读取K线数据到缓冲区
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \param period K线周期
	 * \return 读取的数据字符串
	 * 
	 * 从LMDB数据库读取K线数据并转换为字符串格式
	 */
	std::string	read_bars_to_buffer(const char* exchg, const char* code, WTSKlinePeriod period);

	/*!
	 * \brief 获取实时缓存中的K线数据
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \param period K线周期
	 * \return K线数据结构体指针
	 * 
	 * 从实时缓存中获取最新的K线数据
	 */
	WTSBarStruct* get_rt_cache_bar(const char* exchg, const char* code, WTSKlinePeriod period);

private:
	//////////////////////////////////////////////////////////////////////////
	/*!
	 * \brief LMDB数据库定义说明
	 * 
	 * \details 数据库组织结构：
	 *          
	 *          K线数据：按交易所和周期分库存储
	 *          - m1数据库：./m1/CFFEX（每个交易所一个数据库）
	 *          - m5数据库：./m5/CFFEX
	 *          - d1数据库：./d1/CFFEX
	 *          
	 *          Tick数据：按合约分库存储
	 *          - Tick数据库：./ticks/CFFEX/IF2101（每个合约一个数据库）
	 *          
	 *          这种设计提供了：
	 *          - 高效的数据分区
	 *          - 灵活的数据管理
	 *          - 优化的查询性能
	 *          - 良好的扩展性
	 */
	typedef std::shared_ptr<WtLMDB> WtLMDBPtr;						///< LMDB数据库智能指针类型定义
	typedef faster_hashmap<std::string, WtLMDBPtr> WtLMDBMap;		///< LMDB数据库映射表类型定义

	WtLMDBMap	_exchg_m1_dbs;		///< 按交易所分类的1分钟K线数据库映射
	WtLMDBMap	_exchg_m5_dbs;		///< 按交易所分类的5分钟K线数据库映射
	WtLMDBMap	_exchg_d1_dbs;		///< 按交易所分类的日线K线数据库映射

	WtLMDBMap	_tick_dbs;			///< 按"交易所.合约"为键的Tick数据库映射（如BINANCE.BTCUSDT）

	/*!
	 * \brief 获取K线数据库指针
	 * \param exchg 交易所代码
	 * \param period K线周期
	 * \return LMDB数据库智能指针
	 * 
	 * 根据交易所和K线周期获取对应的LMDB数据库连接
	 */
	WtLMDBPtr	get_k_db(const char* exchg, WTSKlinePeriod period);

	/*!
	 * \brief 获取Tick数据库指针
	 * \param exchg 交易所代码
	 * \param code 合约代码
	 * \return LMDB数据库智能指针
	 * 
	 * 根据交易所和合约代码获取对应的Tick数据库连接
	 */
	WtLMDBPtr	get_t_db(const char* exchg, const char* code);
};

NS_WTP_END
